home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1993 / Internet Info CD-ROM (Walnut Creek) (1993).iso / networking / terms / tipx / cmds.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-11  |  20.6 KB  |  1,080 lines

  1. /*
  2.  * Copyright (c) 1983 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. static char sccsid[] = "@(#)cmds.c    5.8 (Berkeley) 9/2/88";
  20. #endif /* not lint */
  21.  
  22. #include "tip.h"
  23. /*
  24.  * tip
  25.  *
  26.  * miscellaneous commands
  27.  */
  28.  
  29. int    quant[] = { 60, 60, 24 };
  30.  
  31. char    null = '\0';
  32. char    *sep[] = { "second", "minute", "hour" };
  33. static char *argv[10];        /* argument vector for take and put */
  34.  
  35. sigfunc_t    timeout();    /* timeout function called on alarm */
  36. sigfunc_t    stopsnd();    /* SIGINT handler during file transfers */
  37. sigfunc_t    intprompt();    /* used in handling SIG_INT during prompt */
  38. sigfunc_t    intcopy();    /* interrupt routine for file transfers */
  39.  
  40. /*
  41.  * FTP - remote ==> local
  42.  *  get a file from the remote host
  43.  */
  44. getfl(c)
  45.     char c;
  46. {
  47.     char buf[256], *cp, *expand();
  48.     
  49.     putchar(c);
  50.     /*
  51.      * get the UNIX receiving file's name
  52.      */
  53.     if (prompt("Local file name? ", copyname))
  54.         return;
  55.     cp = expand(copyname);
  56.     if ((sfd = creat(cp, 0666)) < 0) {
  57.         printf("\r\n%s: cannot creat\r\n", copyname);
  58.         return;
  59.     }
  60.     
  61.     /*
  62.      * collect parameters
  63.      */
  64.     if (prompt("List command for remote system? ", buf)) {
  65.         unlink(copyname);
  66.         return;
  67.     }
  68.     transfer(buf, sfd, value(EOFREAD));
  69. }
  70.  
  71. /*
  72.  * Cu-like take command
  73.  */
  74. /*ARGUSED*/
  75. cu_take(cc)
  76.     char cc;
  77. {
  78.     int fd, argc;
  79.     char line[BUFSIZ], *expand(), *cp;
  80.  
  81.     if (prompt("[take] ", copyname))
  82.         return;
  83.     if ((argc = args(copyname, argv)) < 1 || argc > 2) {
  84.         printf("usage: <take> from [to]\r\n");
  85.         return;
  86.     }
  87.     if (argc == 1)
  88.         argv[1] = argv[0];
  89.     cp = expand(argv[1]);
  90.     if ((fd = creat(cp, 0666)) < 0) {
  91.         printf("\r\n%s: cannot create\r\n", argv[1]);
  92.         return;
  93.     }
  94.     sprintf(line, "cat %s;echo \01", argv[0]);
  95.     transfer(line, fd, "\01");
  96. }
  97.  
  98. static    jmp_buf intbuf;
  99. /*
  100.  * Bulk transfer routine --
  101.  *  used by getfl(), cu_take(), and pipefile()
  102.  */
  103. transfer(buf, fd, eofchars)
  104.     char *buf, *eofchars;
  105. {
  106.     register int ct;
  107.     char c, buffer[BUFSIZ];
  108.     register char *p = buffer;
  109.     register int cnt, eof;
  110.     time_t start;
  111.     sigfunc_t (*f)();
  112.  
  113.     pwrite(FD, buf, size(buf));
  114.     quit = 0;
  115.     kill(pid, SIGIOT);
  116.     read(repdes[0], (char *)&ccc, 1);  /* Wait until read process stops */
  117.     
  118.     /*
  119.      * finish command
  120.      */
  121.     pwrite(FD, "\r", 1);
  122.     do
  123.         read(FD, &c, 1); 
  124.     while ((c&0177) != '\n');
  125.     ioctl(0, TIOCSETC, &defchars);
  126.     
  127.     (void) setjmp(intbuf);
  128.     f = signal(SIGINT, intcopy);
  129.     start = time(0);
  130.     for (ct = 0; !quit;) {
  131.         eof = read(FD, &c, 1) <= 0;
  132.         c &= 0177;
  133.         if (quit)
  134.             continue;
  135.           if (eof || any(c, eofchars))
  136.               break;
  137.         if (c == 0)
  138.             continue;    /* ignore nulls */
  139.         if (c == '\r')
  140.             continue;
  141.         *p++ = c;
  142.  
  143.         if (c == '\n' && boolean(value(VERBOSE)))
  144.             printf("\r%d", ++ct);
  145.         if ((cnt = (p-buffer)) == number(value(FRAMESIZE))) {
  146.             if (write(fd, buffer, cnt) != cnt) {
  147.                 printf("\r\nwrite error\r\n");
  148.                 quit = 1;
  149.             }
  150.             p = buffer;
  151.         }
  152.     }
  153.     if (cnt = (p-buffer))
  154.         if (write(fd, buffer, cnt) != cnt)
  155.             printf("\r\nwrite error\r\n");
  156.  
  157.     if (boolean(value(VERBOSE)))
  158.         prtime(" lines transferred in ", time(0)-start);
  159.     ioctl(0, TIOCSETC, &tchars);
  160.     write(fildes[1], (char *)&ccc, 1);
  161.     signal(SIGINT, f);
  162.     close(fd);
  163. }
  164.  
  165. /*
  166.  * FTP - remote ==> local process
  167.  *   send remote input to local process via pipe
  168.  */
  169. pipefile()
  170. {
  171.     int cpid, pdes[2];
  172.     char buf[256];
  173.     int status, p;
  174.     extern int errno;
  175.  
  176.     if (prompt("Local command? ", buf))
  177.         return;
  178.  
  179.     if (pipe(pdes)) {
  180.         printf("can't establish pipe\r\n");
  181.         return;
  182.     }
  183.  
  184.     if ((cpid = fork()) < 0) {
  185.         printf("can't fork!\r\n");
  186.         return;
  187.     } else if (cpid) {
  188.         if (prompt("List command for remote system? ", buf)) {
  189.             close(pdes[0]), close(pdes[1]);
  190.             kill (cpid, SIGKILL);
  191.         } else {
  192.             sigfunc_t (*f)();
  193.  
  194.             close(pdes[0]);
  195.             f = signal(SIGPIPE, intcopy);
  196.             transfer(buf, pdes[1], value(EOFREAD));
  197.             signal(SIGPIPE, f);
  198.             while ((p = wait(&status)) > 0 && p != cpid)
  199.                 ;
  200.         }
  201.     } else {
  202.         register int f;
  203.  
  204.         dup2(pdes[0], 0);
  205.         close(pdes[0]);
  206.         for (f = 3; f < 20; f++)
  207.             close(f);
  208.         execute(buf);
  209.         printf("can't execl!\r\n");
  210.         exit(0);
  211.     }
  212. }
  213.  
  214. /*
  215.  * Interrupt service routine for FTP
  216.  */
  217. sigfunc_t
  218. stopsnd()
  219. {
  220.  
  221.     stop = 1;
  222.     signal(SIGINT, SIG_IGN);
  223. }
  224.  
  225. /*
  226.  * FTP - local ==> remote
  227.  *  send local file to remote host
  228.  *  terminate transmission with pseudo EOF sequence
  229.  */
  230. sendfile(cc)
  231.     char cc;
  232. {
  233.     FILE *fd;
  234.     char *fnamex;
  235.     char *expand();
  236.  
  237.     putchar(cc);
  238.     /*
  239.      * get file name
  240.      */
  241.     if (prompt("Local file name? ", fname))
  242.         return;
  243.  
  244.     /*
  245.      * look up file
  246.      */
  247.     fnamex = expand(fname);
  248.     if ((fd = fopen(fnamex, "r")) == NULL) {
  249.         printf("%s: cannot open\r\n", fname);
  250.         return;
  251.     }
  252.     transmit(fd, value(EOFWRITE), NULL);
  253.     if (!boolean(value(ECHOCHECK)) || boolean(value(LINESYNC))) {
  254.         struct sgttyb buf;
  255.  
  256.         ioctl(FD, TIOCGETP, &buf);    /* this does a */
  257.         ioctl(FD, TIOCSETP, &buf);    /*   wflushtty */
  258.     }
  259. }
  260.  
  261. /*
  262.  * Bulk transfer routine to remote host --
  263.  *   used by sendfile() and cu_put()
  264.  */
  265. transmit(fd, eofchars, command)
  266.     FILE *fd;
  267.     char *eofchars, *command;
  268. {
  269.     char *pc, lastc;
  270.     int c, ccount, lcount;
  271.     time_t start_t, stop_t;
  272.     sigfunc_t (*f)();
  273.  
  274.     kill(pid, SIGIOT);    /* put TIPOUT into a wait state */
  275.     stop = 0;
  276.     f = signal(SIGINT, stopsnd);
  277.     ioctl(0, TIOCSETC, &defchars);
  278.     read(repdes[0], (char *)&ccc, 1);
  279.     if (command != NULL) {
  280.         for (pc = command; *pc; pc++)
  281.             send(*pc);
  282.         if (boolean(value(ECHOCHECK)) || boolean(value(LINESYNC)))
  283.             read(FD, (char *)&c, 1);    /* trailing \n */
  284.         else {
  285.             struct sgttyb buf;
  286.  
  287.             ioctl(FD, TIOCGETP, &buf);    /* this does a */
  288.             ioctl(FD, TIOCSETP, &buf);    /*   wflushtty */
  289.             sleep(5); /* wait for remote stty to take effect */
  290.         }
  291.     }
  292.     lcount = 0;
  293.     lastc = '\0';
  294.     start_t = time(0);
  295.     while (1) {
  296.         ccount = 0;
  297.         do {
  298.             c = getc(fd);
  299.             if (stop)
  300.                 goto out;
  301.             if (c == EOF)
  302.                 goto out;
  303.             if (c == 0177 && !boolean(value(RAWFTP)))
  304.                 continue;
  305.             lastc = c;
  306.             if (c < 040) {
  307.                 if (c == '\n') {
  308.                     if (!boolean(value(RAWFTP)))
  309.                         c = '\r';
  310.                 }
  311.                 else if (c == '\t') {
  312.                     if (!boolean(value(RAWFTP))) {
  313.                         if (boolean(value(TABEXPAND))) {
  314.                             send(' ');
  315.                             while ((++ccount % 8) != 0)
  316.                                 send(' ');
  317.                             continue;
  318.                         }
  319.                     }
  320.                 } else
  321.                     if (!boolean(value(RAWFTP)))
  322.                         continue;
  323.             }
  324.             send(c);
  325.         } while (c != '\r' && !boolean(value(RAWFTP)));
  326.         if (boolean(value(VERBOSE)))
  327.             printf("\r%d", ++lcount);
  328.         if (boolean(value(ECHOCHECK)) || boolean(value(LINESYNC))) {
  329.             timedout = 0;
  330.             alarm(value(ETIMEOUT));
  331.             do {    /* wait for prompt */
  332.                 read(FD, (char *)&c, 1);
  333.                 if (timedout || stop) {
  334.                     if (timedout)
  335.                         printf("\r\ntimed out at eol\r\n");
  336.                     alarm(0);
  337.                     goto out;
  338.                 }
  339.             } while ((c&0177) != character(value(PROMPT)));
  340.             alarm(0);
  341.         }
  342.     }
  343. out:
  344.     if (lastc != '\n' && !boolean(value(RAWFTP)))
  345.         send('\r');
  346.     for (pc = eofchars; *pc; pc++)
  347.         send(*pc);
  348.     stop_t = time(0);
  349.     fclose(fd);
  350.     signal(SIGINT, f);
  351.     if (boolean(value(VERBOSE)))
  352.         if (boolean(value(RAWFTP)))
  353.             prtime(" chars transferred in ", stop_t-start_t);
  354.         else
  355.             prtime(" lines transferred in ", stop_t-start_t);
  356.     write(fildes[1], (char *)&ccc, 1);
  357.     ioctl(0, TIOCSETC, &tchars);
  358. }
  359.  
  360. /*
  361.  * Cu-like put command
  362.  */
  363. /*ARGUSED*/
  364. cu_put(cc)
  365.     char cc;
  366. {
  367.     FILE *fd;
  368.     char line[BUFSIZ];
  369.     int argc;
  370.     char *expand();
  371.     char *copynamex;
  372.  
  373.     if (prompt("[put] ", copyname))
  374.         return;
  375.     if ((argc = args(copyname, argv)) < 1 || argc > 2) {
  376.         printf("usage: <put> from [to]\r\n");
  377.         return;
  378.     }
  379.     if (argc == 1)
  380.         argv[1] = argv[0];
  381.     copynamex = expand(argv[0]);
  382.     if ((fd = fopen(copynamex, "r")) == NULL) {
  383.         printf("%s: cannot open\r\n", copynamex);
  384.         return;
  385.     }
  386.     if (boolean(value(ECHOCHECK)))
  387.         sprintf(line, "cat>%s\r", argv[1]);
  388.     else
  389.         sprintf(line, "stty -echo;cat>%s;stty echo\r", argv[1]);
  390.     transmit(fd, "\04", line);
  391. }
  392.  
  393. /*
  394.  * FTP - send single character
  395.  *  wait for echo & handle timeout
  396.  */
  397. send(c)
  398.     char c;
  399. {
  400.     char cc;
  401.     int retry = 0;
  402.  
  403.     cc = c;
  404.     pwrite(FD, &cc, 1);
  405. #ifdef notdef
  406.     if (number(value(CDELAY)) > 0 && c != '\r')
  407.         nap(number(value(CDELAY)));
  408. #endif
  409.     if (!boolean(value(ECHOCHECK))) {
  410. #ifdef notdef
  411.         if (number(value(LDELAY)) > 0 && c == '\r')
  412.             nap(number(value(LDELAY)));
  413. #endif
  414.         return;
  415.     }
  416. tryagain:
  417.     timedout = 0;
  418.     alarm(value(ETIMEOUT));
  419.     read(FD, &cc, 1);
  420.     alarm(0);
  421.     if (timedout) {
  422.         printf("\r\ntimeout error (%s)\r\n", ctrl(c));
  423.         if (retry++ > 3)
  424.             return;
  425.         pwrite(FD, &null, 1); /* poke it */
  426.         goto tryagain;
  427.     }
  428. }
  429.  
  430. sigfunc_t
  431. timeout()
  432. {
  433.     signal(SIGALRM, timeout);
  434.     timedout = 1;
  435. }
  436.  
  437. /*
  438.  * Stolen from consh() -- puts a remote file on the output of a local command.
  439.  *    Identical to consh() except for where stdout goes.
  440.  */
  441. pipeout(c)
  442. {
  443.     char buf[256];
  444.     int cpid, status, p;
  445.     time_t start;
  446.  
  447.     putchar(c);
  448.     if (prompt("Local command? ", buf))
  449.         return;
  450.     kill(pid, SIGIOT);    /* put TIPOUT into a wait state */
  451.     signal(SIGINT, SIG_IGN);
  452.     signal(SIGQUIT, SIG_IGN);
  453.     ioctl(0, TIOCSETC, &defchars);
  454.     read(repdes[0], (char *)&ccc, 1);
  455.     /*
  456.      * Set up file descriptors in the child and
  457.      *  let it go...
  458.      */
  459.     if ((cpid = fork()) < 0)
  460.         printf("can't fork!\r\n");
  461.     else if (cpid) {
  462.         start = time(0);
  463.         while ((p = wait(&status)) > 0 && p != cpid)
  464.             ;
  465.     } else {
  466.         register int i;
  467.  
  468.         dup2(FD, 1);
  469.         for (i = 3; i < 20; i++)
  470.             close(i);
  471.         signal(SIGINT, SIG_DFL);
  472.         signal(SIGQUIT, SIG_DFL);
  473.         execute(buf);
  474.         printf("can't find `%s'\r\n", buf);
  475.         exit(0);
  476.     }
  477.     if (boolean(value(VERBOSE)))
  478.         prtime("away for ", time(0)-start);
  479.     write(fildes[1], (char *)&ccc, 1);
  480.     ioctl(0, TIOCSETC, &tchars);
  481.     signal(SIGINT, SIG_DFL);
  482.     signal(SIGQUIT, SIG_DFL);
  483. }
  484.  
  485. #ifdef CONNECT
  486. /*
  487.  * Fork a program with:
  488.  *  0 <-> local tty in
  489.  *  1 <-> local tty out
  490.  *  2 <-> local tty out
  491.  *  3 <-> remote tty in
  492.  *  4 <-> remote tty out
  493.  */
  494. consh(c)
  495. {
  496.     char buf[256];
  497.     int cpid, status, p;
  498.     time_t start;
  499.  
  500.     putchar(c);
  501.     if (prompt("Local command? ", buf))
  502.         return;
  503.     kill(pid, SIGIOT);    /* put TIPOUT into a wait state */
  504.     signal(SIGINT, SIG_IGN);
  505.     signal(SIGQUIT, SIG_IGN);
  506.     ioctl(0, TIOCSETC, &defchars);
  507.     read(repdes[0], (char *)&ccc, 1);
  508.     /*
  509.      * Set up file descriptors in the child and
  510.      *  let it go...
  511.      */
  512.     if ((cpid = fork()) < 0)
  513.         printf("can't fork!\r\n");
  514.     else if (cpid) {
  515.         start = time(0);
  516.         while ((p = wait(&status)) > 0 && p != cpid)
  517.             ;
  518.     } else {
  519.         register int i;
  520.  
  521.         dup2(FD, 3);
  522.         dup2(3, 4);
  523.         for (i = 5; i < 20; i++)
  524.             close(i);
  525.         signal(SIGINT, SIG_DFL);
  526.         signal(SIGQUIT, SIG_DFL);
  527.         execute(buf);
  528.         printf("can't find `%s'\r\n", buf);
  529.         exit(0);
  530.     }
  531.     if (boolean(value(VERBOSE)))
  532.         prtime("away for ", time(0)-start);
  533.     write(fildes[1], (char *)&ccc, 1);
  534.     ioctl(0, TIOCSETC, &tchars);
  535.     signal(SIGINT, SIG_DFL);
  536.     signal(SIGQUIT, SIG_DFL);
  537. }
  538. #endif
  539.  
  540. #ifdef TIPX
  541. /*
  542.  * filexfer_help
  543.  *
  544.  * Display help for ~X
  545.  *   type = 0, general help, 1 = send help, 2 = receive help
  546.  */
  547. filexfer_help(type)
  548. int type;
  549. {
  550. static char *ghelp[] =
  551. {
  552.     "for send help, type ~Xs?; for receive help, type ~Xr?",
  553.     "where ~ represents your escape character",
  554.     (char *)0,
  555. };
  556. static char *shelp[] =
  557. {
  558.     "XMODEM (CHK, CRC) and XMODEM-1k/CRC",
  559.     "sx [-ak] filename  -a (ASCII) convert NL to CR/LF (default binary)",
  560.     "                   -k use 1024 blocks instead of 128 (XMODEM-1k)",
  561.     "YMODEM/CRC Batch",
  562.     "sy [-af] filelist  -a (ASCII) convert NL to CR/LF (default binary)",
  563.     "                   -f transfer using full pathanme (default simple)",
  564.     "ZMODEM (CRC-16, CRC-32)",
  565.     "sz [-af+nNyrwo] [-w #] [-L #] [-l #]  filelist",
  566.     "                   -a (ASCII) convert NL to CR/LF (default binary)",
  567.     " not all ZMODEM    -f transfer using full pathanme (default simple)",
  568.     " receivers accept  -+ Append to existing destination file",
  569.     " all overwrite     -n overwrite file if source newer",
  570.     " or append         -N overwrite file if source newer or longer",
  571.     " options           -y yes, absolutely overwrite existing file",
  572.     "                   -r Resume/Recover interrupted file transfer",
  573.     "                   -o use CRC-16 instead of CRC-32",
  574.     "                   -w # Window is # bytes (>= 256, multiple of 64)",
  575.     "                   -L # Limit subpacket length to # bytes",
  576.     "                   -l # Limit frame length to # bytes (l must >= L)",
  577.     (char *)0
  578. };
  579. static char *rhelp[] =
  580. {
  581.     "XMODEM (CHK, CRC) (rcvr tries CRC, then checksum)",
  582.     "                          rx [-ab] filename",
  583.     "YMODEM/CRC Batch          ry [-abu]",
  584.     "ZMODEM (CRC-16, CRC-32)   rz [-abu]",
  585.     "Switches:    -a force ASCII translation on receive",
  586.     "             -b force binary transfer",
  587.     "             -u convert uppercase filenames to lower case",
  588.     (char *)0
  589. };
  590. char **hh;
  591.  
  592.     switch(type)
  593.     {
  594.         case 0:  hh = ghelp; break;
  595.         case 1:  hh = shelp; break;
  596.         case 2:  hh = rhelp; break;
  597.     }
  598.     while(*hh)
  599.     {
  600.         fputs(*hh++,stdout);
  601.         fputs("\r\n",stdout);
  602.     }
  603. }
  604. #endif /* TIPX */
  605.  
  606. #ifdef TIPX
  607. /*
  608.  * filexfer
  609.  *
  610.  * Fork a file transfer with:
  611.  *  0 <-> local tty in
  612.  *  1 <-> local tty out
  613.  *  2 <-> local tty out
  614.  *  FD <-> remote tty in/out
  615.  */
  616. filexfer(c)
  617. {
  618.     char buf[256];
  619.     char xcmd[256+24];
  620.     int cpid, status, p;
  621.     time_t start;
  622.  
  623.     putchar(c);
  624.     if(prompt("\r\nfile transfer command? (? for help) ", buf))
  625.         return;
  626.     if(!strncmp(buf,"sz ",3))
  627.         sprintf(xcmd,"tipsz -Z -. %d ",FD);
  628.     else if(!strncmp(buf,"sy ",3))
  629.         sprintf(xcmd,"tipsz -Y -k -. %d ",FD);
  630.     else if(!strncmp(buf,"sx ",3))
  631.         sprintf(xcmd,"tipsz -X -. %d ",FD);
  632.     else if(!strncmp(buf,"rz",2))
  633.         sprintf(xcmd,"tiprz -Z -. %d ",FD);
  634.     else if(!strncmp(buf,"ry",2))
  635.         sprintf(xcmd,"tiprz -Y -. %d ",FD);
  636.     else if(!strncmp(buf,"rx ",3))
  637.         sprintf(xcmd,"tiprz -X -. %d ",FD);
  638.     else if(!strncmp(buf,"?",1))
  639.     {
  640.         filexfer_help(0);
  641.         return;
  642.     }
  643.     else if(!strncmp(buf,"s?",2))
  644.     {
  645.         filexfer_help(1);
  646.         return;
  647.     }
  648.     else if(!strncmp(buf,"r?",2))
  649.     {
  650.         filexfer_help(2);
  651.         return;
  652.     }
  653.     else
  654.     {
  655.         printf("unrecognized transfer command (use sz, rz, etc.)\r\n");
  656.         return;
  657.     }
  658.     strcat(xcmd,buf + 3);
  659.  
  660.     kill(pid, SIGIOT);    /* put TIPOUT into a wait state */
  661.     signal(SIGINT, SIG_IGN);
  662.     signal(SIGQUIT, SIG_IGN);
  663.     unraw();
  664.     read(repdes[0], (char *)&ccc, 1);
  665.     if ((cpid = vfork()) < 0)
  666.         printf("can't fork!\r\n");
  667.     else if (cpid) {
  668.         start = time(0);
  669.         while ((p = wait(&status)) > 0 && p != cpid)
  670.             ;
  671.     } else {
  672.         register int i;
  673.  
  674.         for (i = 3; i < 20; i++)
  675.         {
  676.             if(i != FD)
  677.                 close(i);
  678.         }
  679.         signal(SIGINT, SIG_DFL);
  680.         signal(SIGQUIT, SIG_DFL);
  681.         user_uid();
  682.         execl("/bin/sh", "sh", "-c", xcmd, (char *)0);
  683.         printf("can't execute `%s'\n", xcmd);
  684.         perror("execl");
  685.         exit(0);
  686.     }
  687.     prtime("away for ", time(0)-start);
  688.     write(fildes[1], (char *)&ccc, 1);
  689.     raw();
  690.     signal(SIGINT, SIG_DFL);
  691.     signal(SIGQUIT, SIG_DFL);
  692. }
  693. #endif
  694.  
  695. /*
  696.  * Escape to local shell
  697.  */
  698. shell()
  699. {
  700.     int shpid, status;
  701.     extern char **environ;
  702.     char *cp;
  703.  
  704.     printf("[sh]\r\n");
  705.     signal(SIGINT, SIG_IGN);
  706.     signal(SIGQUIT, SIG_IGN);
  707.     unraw();
  708.     if (shpid = fork()) {
  709.         while (shpid != wait(&status));
  710.         raw();
  711.         printf("\r\n!\r\n");
  712.         signal(SIGINT, SIG_DFL);
  713.         signal(SIGQUIT, SIG_DFL);
  714.         return;
  715.     } else {
  716.         signal(SIGQUIT, SIG_DFL);
  717.         signal(SIGINT, SIG_DFL);
  718.         if ((cp = rindex(value(SHELL), '/')) == NULL)
  719.             cp = value(SHELL);
  720.         else
  721.             cp++;
  722.         shell_uid();
  723.         execl(value(SHELL), cp, 0);
  724.         printf("\r\ncan't execl!\r\n");
  725.         exit(1);
  726.     }
  727. }
  728.  
  729. /*
  730.  * TIPIN portion of scripting
  731.  *   initiate the conversation with TIPOUT
  732.  */
  733. setscript()
  734. {
  735.     char c;
  736.     /*
  737.      * enable TIPOUT side for dialogue
  738.      */
  739.     kill(pid, SIGEMT);
  740.     if (boolean(value(SCRIPT)))
  741.         write(fildes[1], value(RECORD), size(value(RECORD)));
  742.     write(fildes[1], "\n", 1);
  743.     /*
  744.      * wait for TIPOUT to finish
  745.      */
  746.     read(repdes[0], &c, 1);
  747.     if (c == 'n')
  748.         printf("can't create %s\r\n", value(RECORD));
  749. }
  750.  
  751. /*
  752.  * Change current working directory of
  753.  *   local portion of tip
  754.  */
  755. chdirectory()
  756. {
  757.     char dirname[80];
  758.     register char *cp = dirname;
  759.  
  760.     if (prompt("[cd] ", dirname)) {
  761.         if (stoprompt)
  762.             return;
  763.         cp = value(HOME);
  764.     }
  765.     if (chdir(cp) < 0)
  766.         printf("%s: bad directory\r\n", cp);
  767.     printf("!\r\n");
  768. }
  769.  
  770. abort(msg)
  771.     char *msg;
  772. {
  773.  
  774.     kill(pid, SIGTERM);
  775.     disconnect(msg);
  776.     if (msg != NOSTR)
  777.         printf("\r\n%s", msg);
  778.     printf("\r\n[EOT]\r\n");
  779.     daemon_uid();
  780.     (void)uu_unlock(uucplock);
  781.     unraw();
  782.     exit(0);
  783. }
  784.  
  785. finish()
  786. {
  787.     char *dismsg;
  788.  
  789.     if ((dismsg = value(DISCONNECT)) != NOSTR) {
  790.         write(FD, dismsg, strlen(dismsg));
  791.         sleep(5);
  792.     }
  793.     abort(NOSTR);
  794. }
  795.  
  796. sigfunc_t
  797. intcopy()
  798. {
  799.  
  800.     raw();
  801.     quit = 1;
  802.     longjmp(intbuf, 1);
  803. }
  804.  
  805. execute(s)
  806.     char *s;
  807. {
  808.     register char *cp;
  809.  
  810.     if ((cp = rindex(value(SHELL), '/')) == NULL)
  811.         cp = value(SHELL);
  812.     else
  813.         cp++;
  814.     user_uid();
  815.     execl(value(SHELL), cp, "-c", s, 0);
  816. }
  817.  
  818. args(buf, a)
  819.     char *buf, *a[];
  820. {
  821.     register char *p = buf, *start;
  822.     register char **parg = a;
  823.     register int n = 0;
  824.  
  825.     do {
  826.         while (*p && (*p == ' ' || *p == '\t'))
  827.             p++;
  828.         start = p;
  829.         if (*p)
  830.             *parg = p;
  831.         while (*p && (*p != ' ' && *p != '\t'))
  832.             p++;
  833.         if (p != start)
  834.             parg++, n++;
  835.         if (*p)
  836.             *p++ = '\0';
  837.     } while (*p);
  838.  
  839.     return(n);
  840. }
  841.  
  842. prtime(s, a)
  843.     char *s;
  844.     time_t a;
  845. {
  846.     register i;
  847.     int nums[3];
  848.  
  849.     for (i = 0; i < 3; i++) {
  850.         nums[i] = (int)(a % quant[i]);
  851.         a /= quant[i];
  852.     }
  853.     printf("%s", s);
  854.     while (--i >= 0)
  855.         if (nums[i] || i == 0 && nums[1] == 0 && nums[2] == 0)
  856.             printf("%d %s%c ", nums[i], sep[i],
  857.                 nums[i] == 1 ? '\0' : 's');
  858.     printf("\r\n!\r\n");
  859. }
  860.  
  861. variable()
  862. {
  863.     char    buf[256];
  864.  
  865.     if (prompt("[set] ", buf))
  866.         return;
  867.     vlex(buf);
  868.     if (vtable[BEAUTIFY].v_access&CHANGED) {
  869.         vtable[BEAUTIFY].v_access &= ~CHANGED;
  870.         kill(pid, SIGSYS);
  871.     }
  872.     if (vtable[SCRIPT].v_access&CHANGED) {
  873.         vtable[SCRIPT].v_access &= ~CHANGED;
  874.         setscript();
  875.         /*
  876.          * So that "set record=blah script" doesn't
  877.          *  cause two transactions to occur.
  878.          */
  879.         if (vtable[RECORD].v_access&CHANGED)
  880.             vtable[RECORD].v_access &= ~CHANGED;
  881.     }
  882.     if (vtable[RECORD].v_access&CHANGED) {
  883.         vtable[RECORD].v_access &= ~CHANGED;
  884.         if (boolean(value(SCRIPT)))
  885.             setscript();
  886.     }
  887.     if (vtable[TAND].v_access&CHANGED) {
  888.         vtable[TAND].v_access &= ~CHANGED;
  889.         if (boolean(value(TAND)))
  890.             tandem("on");
  891.         else
  892.             tandem("off");
  893.     }
  894.      if (vtable[LECHO].v_access&CHANGED) {
  895.          vtable[LECHO].v_access &= ~CHANGED;
  896.          HD = boolean(value(LECHO));
  897.      }
  898.     if (vtable[PARITY].v_access&CHANGED) {
  899.         vtable[PARITY].v_access &= ~CHANGED;
  900.         setparity();
  901.     }
  902. }
  903.  
  904. /*
  905.  * Turn tandem mode on or off for remote tty.
  906.  */
  907. tandem(option)
  908.     char *option;
  909. {
  910.     struct sgttyb rmtty;
  911.  
  912.     ioctl(FD, TIOCGETP, &rmtty);
  913.     if (strcmp(option,"on") == 0) {
  914.         rmtty.sg_flags |= TANDEM;
  915.         arg.sg_flags |= TANDEM;
  916.     } else {
  917.         rmtty.sg_flags &= ~TANDEM;
  918.         arg.sg_flags &= ~TANDEM;
  919.     }
  920.     ioctl(FD, TIOCSETP, &rmtty);
  921.     ioctl(0,  TIOCSETP, &arg);
  922. }
  923.  
  924. /*
  925.  * Send a break.
  926.  */
  927. genbrk()
  928. {
  929.  
  930.     ioctl(FD, TIOCSBRK, NULL);
  931.     sleep(1);
  932.     ioctl(FD, TIOCCBRK, NULL);
  933. }
  934.  
  935. /*
  936.  * Send a ^S.
  937.  */
  938. #ifdef TIPX
  939. genctls()
  940. {
  941. static char ctls = 0x13;
  942.  
  943.     printf("^S");
  944.     write(FD, &ctls, 1);
  945. }
  946. #endif
  947.  
  948. /*
  949.  * Send a ^Q.
  950.  */
  951. #ifdef TIPX
  952. genctlq()
  953. {
  954. static char ctlq = 0x11;
  955.  
  956.     printf("^Q");
  957.     write(FD, &ctlq, 1);
  958. }
  959. #endif
  960.  
  961. /*
  962.  * control rawthru mode
  963.  */
  964. #ifdef TIPX
  965. rawthru_control(gch)
  966. char gch;
  967. {
  968. extern int rawthru;
  969.     gch &= 0177;
  970.     write(2,&gch,1);
  971.     if(gch == 'R')
  972.     {
  973.         rawthru = 1;
  974.         kill(pid,SIGUSR1);
  975.     }
  976.     else
  977.     {
  978.         rawthru = 0;
  979.         kill(pid,SIGUSR2);
  980.     }
  981. }
  982. #endif
  983.  
  984. /*
  985.  * Suspend tip
  986.  */
  987. suspend(c)
  988.     char c;
  989. {
  990.  
  991.     unraw();
  992.     kill(c == CTRL('y') ? getpid() : 0, SIGTSTP);
  993.     raw();
  994. }
  995.  
  996. /*
  997.  *    expand a file name if it includes shell meta characters
  998.  */
  999.  
  1000. char *
  1001. expand(name)
  1002.     char name[];
  1003. {
  1004.     static char xname[BUFSIZ];
  1005.     char cmdbuf[BUFSIZ];
  1006.     register int pid, l;
  1007.     register char *cp, *Shell;
  1008.     int s, pivec[2];
  1009.  
  1010.     if (!anyof(name, "~{[*?$`'\"\\"))
  1011.         return(name);
  1012.     if (pipe(pivec) < 0) {
  1013.         perror("pipe");
  1014.         /* signal(SIGINT, sigint) */
  1015.         return(name);
  1016.     }
  1017.     sprintf(cmdbuf, "echo %s", name);
  1018.     if ((pid = vfork()) == 0) {
  1019.         Shell = value(SHELL);
  1020.         if (Shell == NOSTR)
  1021.             Shell = "/bin/sh";
  1022.         close(pivec[0]);
  1023.         close(1);
  1024.         dup(pivec[1]);
  1025.         close(pivec[1]);
  1026.         close(2);
  1027.         shell_uid();
  1028.         execl(Shell, Shell, "-c", cmdbuf, 0);
  1029.         _exit(1);
  1030.     }
  1031.     if (pid == -1) {
  1032.         perror("fork");
  1033.         close(pivec[0]);
  1034.         close(pivec[1]);
  1035.         return(NOSTR);
  1036.     }
  1037.     close(pivec[1]);
  1038.     l = read(pivec[0], xname, BUFSIZ);
  1039.     close(pivec[0]);
  1040.     while (wait(&s) != pid);
  1041.         ;
  1042.     s &= 0377;
  1043.     if (s != 0 && s != SIGPIPE) {
  1044.         fprintf(stderr, "\"Echo\" failed\n");
  1045.         return(NOSTR);
  1046.     }
  1047.     if (l < 0) {
  1048.         perror("read");
  1049.         return(NOSTR);
  1050.     }
  1051.     if (l == 0) {
  1052.         fprintf(stderr, "\"%s\": No match\n", name);
  1053.         return(NOSTR);
  1054.     }
  1055.     if (l == BUFSIZ) {
  1056.         fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
  1057.         return(NOSTR);
  1058.     }
  1059.     xname[l] = 0;
  1060.     for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
  1061.         ;
  1062.     *++cp = '\0';
  1063.     return(xname);
  1064. }
  1065.  
  1066. /*
  1067.  * Are any of the characters in the two strings the same?
  1068.  */
  1069.  
  1070. anyof(s1, s2)
  1071.     register char *s1, *s2;
  1072. {
  1073.     register int c;
  1074.  
  1075.     while (c = *s1++)
  1076.         if (any(c, s2))
  1077.             return(1);
  1078.     return(0);
  1079. }
  1080.